#!/bin/bash

# Author: Scott R. Shinn <scott@atomicorp.com>
# https://www.atomicorp.com

# This program is free software; you can redistribute it and/or modify
# it under the terms of the Affero GNU General Public License (AGPL)
#

VERSION=6.0.2

# Functions

# Input validation function 
# check_input <msg> <valid responses regex> <default>
# if <default> is passed on as null, then there is no default
# Example: check_input  "Some question (yes/no) " "yes|no"  "yes"
function check_input {
  message=$1
  validate=$2
  default=$3

  while [ $? -ne 1 ]; do
    echo -n "$message "
    read INPUTTEXT < /dev/tty
    if [ "$INPUTTEXT" == "" -a "$default" != "" ]; then
      INPUTTEXT=$default
      return 1
    fi
    echo $INPUTTEXT | egrep -q "$validate" && return 1
    echo "Invalid input"
  done
}

function download_update() {
	RETRIES=0
	DOWNLOAD_SUCCESS=0
	COMMAND=$1
	TEST=$2
	MSG=$3
	

	echo "$COMMAND"

	while [ $DOWNLOAD_SUCCESS -lt 1 ]; do
		if [ $RETRIES -gt 50 ]; then
			echo "Download not successful: too many failed attempts"
			echo "  rerun  $COMMAND manually"
			return 
		fi

		su - gvm -c "$COMMAND"

		if [ -f $TEST ] ; then
			echo "$COMMAND success"
			DOWNLOAD_SUCCESS=1
		else
			echo "Retrying in 60 seconds..."
			sleep 60
			RETRIES=$(( $RETRIES + 1 ))
		fi
	done

}


echo
echo "GVM Setup, Version: $VERSION"
echo 

# Test for selinux
if [ -f /usr/sbin/getenforce ]; then
SELINUX=$(getenforce 2>/dev/null)
	if [ $? -eq 0 ] ; then
		if [ "$SELINUX" != "Disabled" ]; then
			echo "Error: Selinux is set to ($SELINUX)"
			echo "  selinux must be disabled in order to use openvas"
			echo "  exiting...."
			exit 1
		fi
	fi
fi

#Python 
alternatives --set python /usr/bin/python3

# Set up postgres
if [ ! -f /var/lib/pgsql/initdb_postgresql.log ]; then
	postgresql-setup --initdb --unit postgresql

	systemctl enable postgresql
	systemctl start postgresql

	su - postgres -c "createuser -DRS gvm"
	su - postgres -c "createdb -O gvm gvmd"
	su - postgres -c "psql gvmd -q --command='create role dba with superuser noinherit;'"
	su - postgres -c "psql gvmd -q --command='grant dba to gvm;'"
	su - postgres -c "psql gvmd -q --command='create extension \"uuid-ossp\";'"
	su - postgres -c "psql gvmd -q --command='create extension \"pgcrypto\";'"
	systemctl restart postgresql
fi




# redis setup
if [  -f /etc/redis.conf ]; then
	REDIS_CONF=/etc/redis.conf
elif [ -f /etc/redis/redis.conf ]; then
	REDIS_CONF=/etc/redis/redis.conf
else
	echo "Error: Redis configuration was not detected"
	exit 1
fi


if ! grep -q "^unixsocket /var/run/redis/redis.sock" $REDIS_CONF ; then
  	sed -i -e 's/^\(#.\)\?unixsocket \/.*$/unixsocket \/var\/run\/redis\/redis.sock/' $REDIS_CONF
fi


if ! grep -q ^unixsocketperm.*770 $REDIS_CONF; then
  	sed -i -e 's/^\(#.\)\?unixsocketperm.*$/unixsocketperm 770/' $REDIS_CONF
  	sed -i -e 's/^\(#.\)\?port.*$/port 0/' $REDIS_CONF
fi

# Bugfix for openvas (temporary)
sed -i "s/^save/#save/g" $REDIS_CONF

if grep ^db_address /etc/openvas/openvassd.conf 2>/dev/null; then
	sed -i -e 's/db_address=.*$/db_address=\/var\/run\/redis\/redis.sock/' /etc/openvas/openvas.conf
else
	echo "db_address=/var/run/redis/redis.sock" >> /etc/openvas/openvas.conf
fi

if ! grep -q "^databases 512" $REDIS_CONF; then
	sed -i "s/^databases.*/databases 512/g" $REDIS_CONF
fi 

# Add uer to redis socket
if ! groups gvm |grep -q redis ; then
	usermod -aG redis gvm
fi

systemctl enable redis
systemctl start redis

#Set sysctl
sysctl -w net.core.somaxconn=1024
sysctl vm.overcommit_memory=1
#
if ! grep -q "net.core.somaxconn=1024" /etc/sysctl.conf; then
	echo "net.core.somaxconn=1024"  >> /etc/sysctl.conf
fi
if ! grep -q "vm.overcommit_memory=1" /etc/sysctl.conf; then
	echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
fi

#Disable transparent hugepages
if ! $(grub2-editenv - list | grep -q transparent_hugepage=never) ; then
	grub2-editenv - set "$(grub2-editenv - list | grep kernelopts) transparent_hugepage=never"
fi



# Download NVT updates
echo
echo "Update NVT, CERT, and SCAP data"
echo "Please note this step could take some time."
echo "Once completed, this will be updated automatically every 24 hours"
echo

echo
echo "Updating NVTs...." 
download_update /usr/bin/greenbone-nvt-sync /var/lib/gvm/plugins/plugin_feed_info.inc

echo
echo "Updating GVMD_DATA..."
download_update  "/usr/sbin/greenbone-feed-sync --type GVMD_DATA" /var/lib/gvm/data-objects/gvmd/timestamp

echo
echo "Updating SCAP data..."
download_update "/usr/sbin/greenbone-feed-sync --type SCAP" /var/lib/gvm/scap-data/official-cpe-dictionary_v2.2.xml


echo
echo "Updating CERT data..."
download_update "/usr/sbin/greenbone-feed-sync --type CERT"  /var/lib/gvm/cert-data/timestamp


su - gvm -c "openvas --update-vt-info"


# Handle certs
echo
echo -n "Updating OpenVAS Manager certificates: "
su - gvm -c "/usr/bin/gvm-manage-certs -V >/dev/null 2>&1"
if [ $? -ne 0 ]; then
	su - gvm -c "/usr/bin/gvm-manage-certs -a  >/dev/null 2>&1"
	echo "Complete"
else
	echo "Already Exists"
fi
echo


# Start ospd
systemctl start ospd-openvas

# Start gvmd
systemctl start gvmd 

if [ ! -f /var/lib/gvm/data-objects/gvmd/timestamp ]; then
	echo "Error: GVMD Private data not found. "
	echo "  exiting..."
	exit 1
fi


echo -n "GVMD startup: "
until $(su - gvm -c "/usr/sbin/gvmd --get-users" >/dev/null 2>&1); do
 	echo -n .
        sleep 3 
done    
echo Done

if ! $(su - gvm -c "/usr/sbin/gvmd --get-users | grep -q ^admin$") ; then




	# Configure Admin user
	echo 
	echo "Set the GSAD admin users password."
	echo "The admin user is used to configure accounts,"
	echo "Update NVT's manually, and manage roles."
	echo 

	USERNAME=admin

	# Suppress output of password.
	if [[ -t 0 ]]; then
		stty -echo
	fi

	# Prompt the user for the desired password and verify its accuracy.  
	PASSCONFIRMED=0
	while [ $PASSCONFIRMED -lt 1 ]; do
		read -s -p "Enter Administrator Password: " PASSWORD
		echo

		read -s -p "Verify Administrator Password: " PASSWORD2
		echo


		if [ "$PASSWORD" == "$PASSWORD2" ]; then
			if [ "$PASSWORD" == "" ]; then
				echo "Empty password not allowed."
				PASSCONFIRMED=0
			else
				PASSCONFIRMED=1
			fi
			echo
		else
			echo "Passwords do not match"
			echo
		fi
	done
	stty echo


	# Create admin user
	su - gvm -c "/usr/sbin/gvmd  --create-user=${USERNAME}>/dev/null 2>&1"
	su - gvm -c "/usr/sbin/gvmd  --user=${USERNAME} --new-password=\"${PASSWORD}\""

	# Set the feed owner
	FEED_OWNER=$(su - gvm -c "/usr/sbin/gvmd --get-users --verbose" | awk '/^admin / {print $2}')
	if [[ $FEED_OWNER == "" ]]; then
		echo "Error: Feed owner could not be found"
		exit 1
	fi
	su - gvm -c "/usr/sbin/gvmd --modify-setting 78eceaec-3385-11ea-b237-28d24461215b --value $FEED_OWNER"

fi

systemctl start gsad
systemctl enable ospd-openvas
systemctl enable gvmd
systemctl enable gsad

# Set firewall rules
DEFAULT_ZONE=$(firewall-cmd --get-default-zone)
firewall-cmd --zone=$DEFAULT_ZONE --permanent --add-service=https
firewall-cmd --reload

# Planned, this is not multi-run safe yet
#if ! grep -q "Updating CERT info succeeded" /var/log/gvm/gvmd.log; then
#	echo "GVMD startup can take some time to complete. Please be patient"
#	echo
#	echo -n "GVMD initializing: "
#	COUNTER=0
#	tail -f /var/log/gvm/gvmd.log | while read LOGLINE; do
#		if [ $COUNTER -ge 600 ]; then
#			echo "Error: gvmd startup was not detected successfully"
#			echo "  exiting..."
#			exit 1
#		 fi
#
#		 if [[ "${LOGLINE}" == *"sync_cert: Updating CERT info succeeded"* ]]; then
#			echo "Complete"
#			break
#		 else
#			echo -n .
#		 fi
#
#		((COUNTER++))
#	done
#fi



echo
echo "Setup complete"
echo "  Log in to GSAD at https://localhost"
echo
echo

# End

